Skip to content

Conversation

grdsdev
Copy link
Contributor

@grdsdev grdsdev commented Oct 6, 2025

Summary

This PR ports the getClaims method from supabase/auth-js#1030 to the Flutter client. The method supports verifying JWTs (both symmetric and asymmetric) and returns the entire set of claims in the JWT payload.

Close #1117

Changes

  • New getClaims() method in GoTrueClient for JWT verification and claims extraction
  • 📦 Base64URL utilities (RFC 4648 compliant) for encoding/decoding JWT parts
  • 🔒 JWT types: JwtHeader, JwtPayload, DecodedJwt, GetClaimsResponse
  • 🛠️ Helper functions: decodeJwt() and validateExp()
  • 🚨 New exception: AuthInvalidJwtException for JWT-related errors
  • Comprehensive tests for getClaims, JWT helpers, and base64url utilities

Implementation Details

The method handles different JWT signature algorithms:

  • HS256 (symmetric): Verified server-side via getUser() call - we cannot verify HMAC signatures client-side without the secret key
  • RS256/ES256 (asymmetric): Verified client-side using public key from JWKS endpoint

Usage Example

// Get claims from current session
final response = await client.getClaims();
print(response.claims['sub']); // User ID
print(response.claims['email']); // User email
print(response.claims['role']); // User role

// Get claims from explicit JWT
final response = await client.getClaims(jwt: accessToken);

// Allow expired tokens (useful for inspecting claims without validation)
final response = await client.getClaims(
  jwt: expiredToken,
  options: GetClaimsOptions(allowExpired: true),
);

Related

🤖 Generated with Claude Code

…aims

This introduces a new `getClaims` method that supports verifying JWTs
(both symmetric and asymmetric) and returns the entire set of claims
in the JWT payload.

Key changes:
- Add `getClaims()` method to GoTrueClient for JWT verification and claims extraction
- Implement base64url encoding/decoding utilities (RFC 4648)
- Add JWT types: JwtHeader, JwtPayload, DecodedJwt, GetClaimsResponse
- Add helper functions: decodeJwt() and validateExp()
- Add AuthInvalidJwtException for JWT-related errors
- Include comprehensive tests for getClaims, JWT helpers, and base64url utilities

The method verifies JWTs by calling getUser() to validate against the
server, supporting both HS256 (symmetric) and RS256/ES256 (asymmetric)
algorithms.

Note: This is an experimental API and may change in future versions.

Ported from: supabase/auth-js#1030

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@grdsdev grdsdev marked this pull request as draft October 6, 2025 20:38
Following up on the initial getClaims implementation, this commit:

- Removes experimental status from getClaims() method
- Adds GetClaimsOptions class with allowExpired parameter
- Updates getClaims() to accept optional options parameter
- Improves documentation to better describe the method's behavior
- Exports helper functions (decodeJwt, validateExp) for public use
- Adds tests for allowExpired option

The allowExpired option allows users to extract claims from expired
JWTs without throwing an error during expiration validation. This is
useful for scenarios where you need to access JWT data even after
expiration.

Ported from: supabase/auth-js#1078

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@grdsdev grdsdev added the enhancement New feature or request label Oct 6, 2025
grdsdev and others added 5 commits October 6, 2025 17:50
Updates getClaims() documentation and comments to clarify that the
method always uses server-side verification via getUser(). This approach
gracefully handles edge cases such as:

- Key rotation scenarios where JWKS cache might not have the new signing key
- Symmetric JWTs (HS256) that require server-side verification
- Revoked or invalidated tokens that are still unexpired

This aligns the implementation intent with the auth-js behavior where
getClaims() falls back to getUser() when the signing key is not found
in JWKS or when client-side verification is not available.

The Flutter implementation uses this server-side verification approach
for all JWT types, providing robust and consistent validation regardless
of the signing algorithm.

Related: supabase/auth-js#1080

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Fixed the _base64ToBase64url method to preserve padding characters
when pad=true is specified. Previously, padding was always stripped
during conversion, causing encode(data, pad: true) to return unpadded
output.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@grdsdev grdsdev requested review from Vinzent03 and dshukertjr and removed request for Vinzent03 October 7, 2025 09:40
@grdsdev grdsdev marked this pull request as ready for review October 7, 2025 09:40
@coveralls
Copy link

Pull Request Test Coverage Report for Build 18308462635

Details

  • 84 of 170 (49.41%) changed or added relevant lines in 5 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-1.3%) to 79.602%

Changes Missing Coverage Covered Lines Changed/Added Lines %
packages/gotrue/lib/src/types/auth_exception.dart 2 4 50.0%
packages/gotrue/lib/src/gotrue_client.dart 14 47 29.79%
packages/gotrue/lib/src/types/jwt.dart 21 72 29.17%
Totals Coverage Status
Change from base Build 18289898404: -1.3%
Covered Lines: 3321
Relevant Lines: 4172

💛 - Coveralls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add getClaims method
2 participants